﻿///////////////////////////////////////////////////////////////////////////////
/// Copyright (c) by longshuang@msn.cn 2014-2015.
/// All rights reserved.
///
/// @File	: Engine.TCP.hpp
/// @Brief	: Engine.Network的一个通用实现方案
/// @Author	: Leo Zhao <longshuang@msn.cn>
/// @Date	: 2015-08-24
///
/// CHANGELOG
/// 	2015-08-24	初版提交
///////////////////////////////////////////////////////////////////////////////
#ifndef		__ENGINE_TCP_HPP_INCLUDE__
#define		__ENGINE_TCP_HPP_INCLUDE__

#include	"Engine.Network.hpp"
#include	"Engine.Memory.hpp"
#include	"Engine.Log.hpp"

#include	<map>

namespace Engine { namespace TCP {

	class IClient : public Network::Socket::IListener {
	public:
		IClient();
		virtual ~IClient();

		virtual void	OnConnect(uint32_t uRemoteIp, uint16_t uPort) override;
		virtual bool	OnReceive(char * pData, size_t uSize) override;
		virtual void	OnClose(int nReason) override;
		
		/// @Brief	: 初始化Socket客户端
		/// @Param	: pToken	签名验证时需要的密文(与服务器统一约定)
		/// @Param	: szLogger	日志记录
		/// @Return	: NONE
		virtual void	Init(const char * pToken, const char * szLogger);

		/// @Brief	: 连接服务器
		/// @Param	: szIP		服务器地址
		/// @Param	: nPort		服务器开放的端口
		/// @Return	: 是否成功， 0成功， 其他错误见Engine.Network
		virtual int		Connect(const char * szIP, int nPort);

		/// @Brief	: 主线程调用，触发解析之前收到的所有的网络包
		/// @Param	: NONE
		/// @Return	: NONE
		virtual void	Breath();

		/// @Brief	: 发送数据
		/// @Param	: nPF		协议簇，为支持ProtocolBuffer等序列化库，直接将PF写入附加头中
		/// @Param	: pData		数据地址
		/// @Param	: uSize		数据大小
		/// @Return	: 发送的结果，0成功，其他错误见Engine.Network
		virtual int		Send(int nPF, void * pData, uint32_t uSize);

		/// @Brief	: 协议处理的具体实现
		/// @Param	: nPF		协议簇
		/// @Param	: pData		来自服务器的数据地址
		/// @Param	: uSize		该数据的大小
		/// @Return	: NONE
		virtual void	ProcessMessage(int nPF, void * pData, uint32_t uSize) = 0;

		/// @Brief	: 关闭连接
		/// @Param	: NONE
		/// @Return	: NONE
		virtual void	Close();

		/// @Brief	: 取得日志接口
		/// @Param	: NONE
		/// @Return	: 日志接口
		inline Log::Logger &	Logger() { return GLogger(_szLogger); }

	private:
		Network::Socket *	_pClient;
		Memory::RWBuffer	_iCache;
		uint64_t			_nSerial;
		unsigned char		_pToken[16];
		char				_szLogger[64];
	};

	class IServer : public Network::ServerSocket::IListener {
	public:
		struct Connection {
			uint64_t	nConnId;
			uint32_t	nRemoteIp;
			uint16_t	nPort;
			uint64_t	nSerial;
		};

	public:
		IServer();
		virtual ~IServer();

		virtual void	OnAccept(uint64_t nConnId, uint32_t uRemoteIp, uint16_t uPort, int nState) override;
		virtual bool	OnReceive(uint64_t nConnId, char * pData, size_t uSize) override;
		virtual void	OnClose(uint64_t nConnId, int nReason) override;

		/// @Brief	: 初始化ServerSocket
		/// @Param	: pToken	签名验证时需要的密文(与服务器统一约定)
		/// @Param	: szLogger	日志记录
		/// @Return	: NONE
		virtual void	Init(const char * pToken, const char * szLogger);

		/// @Brief	: 启动服务器监听
		/// @Param	: szIP		监听的IP
		/// @Param	: nPort		监听的端口
		/// @Return	: 是否成功监听，0成功，其他错误信息见Engine.Network
		virtual int		Listen(const char * szIP, int nPort);

		/// @Brief	: 关闭一个客户端的连接
		/// @Param	: nConnId	服务器分配的客户端连接ID
		/// @Return	: NONE
		virtual void	Close(uint64_t nConnId);

		/// @Brief	: 关闭所有的连接
		/// @Param	: NONE
		/// @Return	: NONE
		virtual void	Shutdown();

		/// @Brief	: 主线程调用，触发一次累计接收信息的处理
		/// @Param	: NONE
		/// @Return	: NONE
		virtual void	Breath();

		/// @Brief	: 发送消息给客户端
		/// @Param	: nConnId	服务器分配的客户端连接ID
		/// @Param	: nPF		协议簇，为支持ProtocolBuffer等序列化库，直接将PF写入附加头中
		/// @Param	: pData		需要发送的消息
		/// @Param	: uSize		数据的大小
		/// @Return	: 是否成功发送，0成功，其他错误代码见Engine.Network
		virtual int		Send(uint64_t nConnId, int nPF, void * pData, uint32_t uSize);

		/// @Brief	: 向所有已连接的客户端广播消息
		/// @Param	: nPF		协议簇，为支持ProtocolBuffer等序列化库，直接将PF写入附加头中		
		/// @Param	: pData		需要发送的消息
		/// @Param	: uSize		数据的大小
		/// @Return	: 返回是否发送成功，同Send
		virtual int		Broadcast(int nPF, void * pData, uint32_t uSize);

		/// @Brief	: 具体的消息处理逻辑
		/// @Param	: nConnId	服务器分配的客户端连接ID
		/// @Param	: nPF		协议簇
		/// @Param	: pData		来自客户端的数据地址
		/// @Param	: uSize		该数据的大小
		/// @Return	: NONE
		virtual void	ProcessMessage(uint64_t nConnId, int nPF, void * pData, uint32_t uSize) = 0;

		/// @Brief	: 得到一个ConnectionInfo
		/// @Param	: nConnId	服务器分配的ID
		/// @Return	: 返回该客户端网络的信息
		virtual Connection *	GetClient(uint64_t nConnId);

		/// @Brief	: 取得日志接口
		/// @Param	: NONE
		/// @Return	: 日志接口
		inline Log::Logger &	Logger() { return GLogger(_szLogger); }

	private:
		std::map<uint64_t, Connection>	_mpConns;
		Network::ServerSocket *			_pServer;
		Memory::RWBuffer				_iCache;
		unsigned char					_pToken[16];
		char							_szLogger[64];
	};

}}

#endif//!	__ENGINE_TCP_HPP_INCLUDE__
